// SoundManager.cpp
////////////////////////////////////////////////////////////////////////////////////////////////////

#include "SoundManager.h"
#include "Core/Commons.h"
#include "Io/FileSystem/FileHeader.h"
#include "Application.h"
#include "IFileSystem.h"
//#include "IO/FileSystem/BinaryFile.h"


#ifdef OS_IPHONE
	#include <string.h>
	#include "SoundEngine.h"
#endif

using namespace irr;
using namespace io;
////////////////////////////////////////////////////////////////////////////////////////////////////

//Loop constants
#define LOOP_INFINITE	(0x7FFFFFFF)
#define LOOP_ONCE		(0x00000001)
#define LOOP_TWICE		(0x00000002)
#define MAX_FREQ		44100.0f

////////////////////////////////////////////////////////////////////////////////////////////////////

SoundManager::SoundManager()
{
	for (int i = 0; i < SOUND_NUM_FILES; i++)
	{
		m_SoundData[i] = NULL;
		lengthsSound[i] = 0;
	}

	m_soundWrap = NEW CSoundWrap();

	m_soundWrap->Init();
	m_soundWrap->Start();

	
	m_bPlaySounds = false; // Must call SetSoundStatus(true) to activate playing sounds

		

	m_bSoundAndMusicProcessing = false;
		
	m_fileHeader = NEW FileHeader();

#ifdef OS_IPHONE
	pthread_mutex_init(&s_mutex, NULL);
#endif
}

////////////////////////////////////////////////////////////////////////////////////////////////////

SoundManager::~SoundManager()
{

	for (int i = 0; i < SOUND_NUM_FILES; i++)
	{
		m_soundWrap->SampleFree(i);
		SAFE_DEL(m_SoundData[i]);
	}

	SAFE_DEL(m_soundWrap);
	SAFE_DEL(m_fileHeader);
#ifdef OS_IPHONE
	pthread_mutex_destroy(&s_mutex);
#endif

}

////////////////////////////////////////////////////////////////////////////////////////////////////

int SoundManager::loadNeededSounds(bool justLoadSamples)
{
	lockProcessing();

	for(int nIndex = 0; nIndex < SOUND_NUM_FILES; nIndex++)
	{
		if(m_SoundData[nIndex])
			m_soundWrap->SampleLoad(nIndex, (char*) m_SoundData[nIndex], lengthsSound[nIndex]);
	}
	
	unlockProcessing();
	return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int SoundManager::LoadSoundBuffers()
{
	IReadFile* pFile =  Application::instance()->GetDevice()->getFileSystem()->createAndOpenFile("sounds.pack");
	
	if (!pFile)
	{
		return -1;
	}

	// read the header
	if (m_fileHeader->LoadHeader(pFile))
	{
		pFile->drop();
		return -1;
	}

	//Read the number of sounds
	if (m_fileHeader->GetNumber() != SOUND_NUM_FILES)
	{
		pFile->drop();
		return -1;
	}

	for (int i = 0; i < SOUND_NUM_FILES; i++)
	{
		if (!m_SoundData[i])
		{
			//Alloc memory for it
			lengthsSound[i] = m_fileHeader->GetSize(i);
			if(lengthsSound[i] > 0)
			{
				m_SoundData[i] = NEW unsigned char[lengthsSound[i]];
				if (!m_SoundData[i])
				{
					LOG("global", " !!! Load Sound error !!! %d\n", i);
					pFile->drop();
					return -1;
				}
				pFile->read(m_SoundData[i], lengthsSound[i]);
			}
		}
		else
		{
			pFile->seek(m_fileHeader->GetSize(i) , true);
		}
	}
	//No error. Close the file and return 0.
	pFile->drop();

	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SoundManager::initialize()
{
	if(!m_soundWrap->m_bIsSoundAndMusicInitialized)
	{
		lockProcessing();
#ifdef OS_IPHONE
		SoundEngine_Initialize(44100.0f);
		SoundEngine_SetListenerPosition( 0.0, 0.0, /*kListenerDistance*/0.0 );
#endif
		m_soundWrap->m_bIsSoundAndMusicInitialized = true;
		unlockProcessing();
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SoundManager::destroy()
{
	if(!m_soundWrap->m_bIsSoundAndMusicInitialized)
	{
		return;
	}

	lockProcessing();
	if(m_bSoundAndMusicProcessing)
	{
		unlockProcessing();		
		return;
	}
	stopAllSounds(false);


#ifdef OS_IPHONE
	SoundEngine_Teardown();
#endif

	m_soundWrap->m_bIsSoundAndMusicInitialized = false;
	
	unlockProcessing();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SoundManager::SetMasterVolume( unsigned char vol )
{
	lockProcessing();
	//if( vol < 0 )
	//	vol = 0;
	if( vol > SOUND_CONTROL_VOLUME_MAX )
		vol = SOUND_CONTROL_VOLUME_MAX;

	m_nMasterVolume = vol;
	if(m_soundWrap) 
		m_soundWrap->SetMasterVolume(vol);

	SetSoundStatus(vol > 0);

	unlockProcessing();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SoundManager::SetSfxVolume( unsigned char vol )
{
	lockProcessing();
	//if( vol < 0 )
	//	vol = 0;
	if( vol > SOUND_CONTROL_VOLUME_MAX )
		vol = SOUND_CONTROL_VOLUME_MAX;

	m_nSoundVolume = vol;
	if(m_soundWrap) 
		m_soundWrap->SetSfxVolume(vol);

	unlockProcessing();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SoundManager::SetMusicVolume( unsigned char vol )
{
	lockProcessing();
	//if( vol < 0 )
	//	vol = 0;
	if( vol > MUSIC_CONTROL_VOLUME_MAX )
		vol = MUSIC_CONTROL_VOLUME_MAX;

	m_nMusicVolume = vol;
	if(m_soundWrap) 
		m_soundWrap->SetMusicVolume(vol);

	unlockProcessing();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SoundManager::playSound(int soundId, int loopCount)
{
	return;
	if (!m_bPlaySounds || !m_soundWrap)
		return;

	lockProcessing();
	m_soundWrap->SampleStart(soundId, loopCount==LOOP_INFINITE?true:false, false);	
	unlockProcessing();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SoundManager::stopSound(int soundId, int mode)
{
//	LOG("global", "stopSound soundId = %d\n", soundId);
	if(!m_soundWrap) 
		return;

	lockProcessing();
	m_soundWrap->SampleStop(soundId);
	unlockProcessing();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SoundManager::stopAllSounds(bool bUseLockProcessing)
{
//	LOG("global", "stopAllSounds START\n");
	if(!m_soundWrap) 
		return;

	if(bUseLockProcessing)
		lockProcessing();

	for(int i=0;i<SOUND_NUM_FILES;i++)
	{
//		LOG("global", "%d ", i);
		m_soundWrap->SampleStop(i);
	}
		
	if(bUseLockProcessing)
		unlockProcessing();

//	LOG("global", "stopAllSounds END\n");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool SoundManager::SamplePlaying(int id)
{
	lockProcessing();
	bool retVal = 0;
	if(m_soundWrap) m_soundWrap->SamplePlaying(id);
	unlockProcessing();
	return retVal;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool SoundManager::isPlaying()
{ 
	if(!m_soundWrap)
		return false;

	for(int i=0;i<SOUND_NUM_FILES;i++)
	{
		if(m_soundWrap->SamplePlaying(i))
			return true;
	}

	return false;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool SoundManager::isPlaying(int id)
{ 
	if(id < 0 || id >= SOUND_NUM_FILES || !m_soundWrap)
		return false;

	return m_soundWrap->SamplePlaying(id);	
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SoundManager::update()						
{
	lockProcessing();
	

	if(m_soundWrap) 
		m_soundWrap->Update();

	unlockProcessing();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
